/*
    VR-TOOLBOX
    Copyright (C) 2013 Nicolas GUILLIER 

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/
package com.ngu.headingcalc;

import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;

public class PotarManager 
implements OnCheckedChangeListener, OnTouchListener {

	MainActivity parent;
	Control currentControl;
	boolean touchInProgress = false;
	double lastAngle = 0F;
	float refX;
	float refY;

	float currentControledValue;
	float lastPublishedValue;
//	private AudioManager audioMngr;

	public PotarManager(MainActivity activity) {
//		audioMngr = null;
		refX = 0f;
		refY = 0f;
		parent = activity;
		currentControl = Control.WindDir;
	}
	
	public void initPotar() {
		rotateView(Control.WindDir.getImageId(), parent.getWindDir());
		rotateView(Control.Heading.getImageId(), parent.getHeading());
		rotateView(Control.Target.getImageId(), parent.getTarget());
	}
	
	private void playClic(View v) {
//		if (audioMngr == null) 
//		{
//			audioMngr = (AudioManager) v.getContext().getSystemService(Context.AUDIO_SERVICE);
//		}
//		audioMngr.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, 1f);
	}

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {		
		currentControl = Control.getControlById(checkedId);
	}

	@Override
	public boolean onTouch(View v, MotionEvent ev) {
		final int action = ev.getAction();
		
		if ( (refX==0f) && (refY==0f) && (v != null) ) {
			
			refY = v.getHeight() / 2;
			refX = v.getWidth() / 2;
			//Log.d("HeadCalc", "refX=" + refX + ", refY=" + refY);
			//Log.d("HeadCalc", "width=" + v.getWidth() + ", height=" + v.getHeight());
		}		
		
		switch (action & MotionEvent.ACTION_MASK) {

		case MotionEvent.ACTION_DOWN: 
			touchInProgress = true;
			initControledValue();
			lastAngle = computeAngle(ev.getX(), ev.getY());
			break;

		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL: 
		case MotionEvent.ACTION_POINTER_DOWN:
			touchInProgress = false;
			if (currentControl != Control.Heading) {
				parent.redrawPolar();
			}
			break;

		case MotionEvent.ACTION_MOVE:
			int currentAngle = computeAngle(ev.getX(), ev.getY());
			if (touchInProgress) {
				if (Math.abs(currentAngle - lastAngle) < 180)
				{
					currentControledValue += (currentAngle - lastAngle) / 3;

					if ( ( (currentControledValue - lastPublishedValue) >= 1F) || ( (currentControledValue - lastPublishedValue) <= -1F) ) 
					{
						publishControledValue();
						lastPublishedValue = currentControledValue;

						// make a clic and rotate the potar!
						playClic(v);
						
						rotateView(currentControl.getImageId(), Math.round(currentControledValue));							
					}
				}
				lastAngle = currentAngle;
			}
			break;

		default: return false;
		}
		return true;
	}

	private void initControledValue() {
		switch (currentControl) {
		case Heading: 
			currentControledValue = parent.getHeading(); 
			break;
		case Target:
			currentControledValue = parent.getTarget();
			break;
		case WindDir:
			currentControledValue = parent.getWindDir();
			break;
		case WindSpeed:
			currentControledValue = parent.getWindSpeed() * 10;
			break;
		}
		lastPublishedValue=currentControledValue;
	}

	private void publishControledValue() {
		switch (currentControl) {
		case WindDir:  
			parent.setWindDir((Math.round(currentControledValue) + 360) % 360);
			break;
		case WindSpeed:
			if (currentControledValue >= 0F)
			{
				if (currentControledValue <= 690F) {
					parent.setWindSpeed(Math.round(currentControledValue) / 10F);
				} else {
					parent.setWindSpeed(69F);
				}					
			} else {
				parent.setWindSpeed(0F);
			}
			break;
		case Heading:
			parent.setHeading((Math.round(currentControledValue) + 360) % 360);
			break;
		case Target:
			parent.setTarget((Math.round(currentControledValue) + 360) % 360);
			break;		
		}		
	}

	private void rotateView(int imageId, int delta) {
		ImageView view = null;
		if (imageId != -1) {
			view = (ImageView) parent.findViewById(imageId);
		}
		if (view != null) {
			view.setRotation(delta);
		}
	}

	private int computeAngle(float x, float y) {		
		float alpha = 0.0F;
		if (refY == y) {
			if (refX == x) {
				alpha = 0;
			} else if (refX < x) {
				alpha = 90.0F;
			} else if (refX > x) {
				alpha = 270.0F;
			}
		} else {
			float atan = (float) Math.toDegrees(Math.atan( (x - refX)/(y - refY)));			
			if (refY > y) {
				if (refX < x) {
					alpha = -atan;
				} else if (refX > x) {
					alpha = 360.0F - atan;
				}
			} else if (refY < y) {
				alpha = 180.0F - atan;
			}
		}
		return Math.round(alpha);
	}

	public enum Control {
		WindDir (R.id.windDirRadio, R.id.windView),
		WindSpeed (R.id.windForceRadio, -1),
		Heading (R.id.headingRadio, R.id.headingView), 
		Target (R.id.targetRadio, R.id.targetView);

		private int radioBtnId;
		private int imageId;

		private Control(int radioBtnId, int imageId) {
			this.radioBtnId = radioBtnId;
			this.imageId = imageId;
		}

		public static Control getControlById(int radioBtnId) 
		{
			for (Control control : Control.values()) {
				if (control.getRadiotBtnId() == radioBtnId) {
					return control;
				}
			}
			return null;
		}

		public int getImageId() {
			return imageId;
		}
		private int getRadiotBtnId() {
			return radioBtnId;
		}
	}
}

